# Copyright 2012 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
from models.models import Student, Course, Unit, Lesson, Question
import webapp2, jinja2

from google.appengine.api import users, memcache
import yaml
import traceback
from controllers import getLogger
import json
import logging

template_dir = os.path.join(os.path.dirname(__file__), '../views')
jinja_environment = jinja2.Environment(
    loader=jinja2.FileSystemLoader(template_dir))

SITE_SETUP_FILE = os.path.join(os.path.dirname(__file__),'../sitesetup.yaml')

log = getLogger(__name__)


class SiteSetup(object):
    setup = None
    lastload = 0
    def get_site_setup(self):
        if self.setup is None or self.lastload < os.path.getmtime(SITE_SETUP_FILE):
            self.setup = yaml.load(open(SITE_SETUP_FILE, 'rb'))
            self.lastload = os.path.getmtime(SITE_SETUP_FILE)
            log.info("Reloaded Site Setup")
        else:
            log.info("Site Setup Not changed %s >= %s " % (self.lastload, os.path.getmtime(SITE_SETUP_FILE)))

        return self.setup


SITE_SETUP = SiteSetup()

"""
Base handler
"""

class BaseCourseHandler(webapp2.RequestHandler):
    templateValue = {}
    def loadcoursecode(self, coursecode=None, field=None):

        self.coursecode = coursecode
        if self.coursecode is not None: 
            self.templateValue.update({ 
                        'site' : SITE_SETUP.get_site_setup(),
                        'coursesetup' : self.course(Course.all())[0], 
                        'coursecode' : coursecode,
                        'registered' : set() })
        else:
            self.templateValue.update({ 
                        'site' : SITE_SETUP.get_site_setup(),
                        'courses' : Course.all(),
                        'coursesetup' : None, 
                        'coursecode' : None,
                        'registered' :  set()})
        user = users.get_current_user()
        if user is not None:
            self.templateValue.update({
                        'registered' : set([ c.coursecode for c in Student.all().filter("email =", user.email()) ])
                        })
        
        

    def dispatch(self):
        logging.error("Performing dispatch ")
        args, kwargs = self.request.route_args, self.request.route_kwargs
        if kwargs:
            args = ()
        # Load the coursesetup, if one has been provided.
        try:
            self.loadcoursecode(*args, **kwargs)
        except Exception, e:
            log.error("Error %s " % traceback.format_exc())
        return webapp2.RequestHandler.dispatch(self)

    def key(self, name):
        logging.error("Key for course %s " % self.coursecode)
        return "%s:%s" % (self.coursecode, name)
  
    def course(self, query):
        logging.error("Filtering for course %s " % self.coursecode)
        return query.filter("coursecode =", self.coursecode)
    
    def clear_cache(self, cachename):
        cachekey = self.key(cachename)
        memcache.delete(cachekey)
  
    def getcache(self, cachename, queryFunction):
        '''
        Gets something from the cache using the queryFunction to create a new copy if 
        not already in the cache.
        :param cachename:
        :param queryFunction:
        '''
        cachekey = self.key(cachename)
        cached = memcache.get(cachekey)
        if cached is None:
            cached = queryFunction()
            logging.error("Cache Miss %s %s" % ( cachekey, cached))
            memcache.add(cachekey, cached)
        else:
            logging.error("Cache Hit %s %s" %  ( cachekey, cached))
            
        return cached
    
    def get_course(self):
        return self.getcache('course', lambda: self.course(Course.all()).get())

    def save_course(self, course):
        self.clear_cache('course')
        course.put()
          
    def get_units(self):
        return self.getcache('units', lambda : self.course(Unit.all()).order('id'))

    def get_unit(self, unit_id):
        for u in self.get_units():
            if u.unit_id == unit_id:
                return u
  
    def get_lessons(self, unit_id):
        return self.getcache('lessons' + str(unit_id), 
                                lambda: self.course(Lesson.all()).filter('unit_id =', unit_id).order('id'))
        
    def get_lesson(self, unit_id, lesson_id):
        for l in self.get_lessons(unit_id):
            if l.id == lesson_id:
                return l

    def get_activities(self, activity_id):
        return self.getcache('questions' + str(activity_id),
                            lambda: self.course(Question.all()).filter("activity_id =", activity_id).order('id'))

     
class BaseHandler(BaseCourseHandler):
    user = users.get_current_user()
    log.info(user)

    def getUser(self, course):
        """Validate user exists and in early access list."""
        user = users.get_current_user()
        if not user:
            self.redirect(users.create_login_url(self.request.uri))
        else:
            return user

    def render(self, templateFile):
        template = jinja_environment.get_template(templateFile)
        self.response.out.write(template.render(self.templateValue))


"""
Student Handler
"""


    
    



class StudentHandler(BaseCourseHandler):

    def getStudent(self, coursecode):
        user = users.get_current_user()
        if user:
            return self.getcache(user.email(), 
                               lambda : Student.get_by_key_name(self.key(user.email())))
        else:
            self.redirect(users.create_login_url(self.request.uri))

    def render(self, templateFile):
        template = jinja_environment.get_template(templateFile)
        html = template.render(self.templateValue)
        self.response.out.write(html)

class CourseListHandler(BaseHandler):
    
    def get(self):
        user = users.get_current_user()
        if user:
            self.templateValue['email'] = user.email()
            self.templateValue['logoutUrl'] = users.create_logout_url('/')

        self.templateValue['navbar'] = {}
        
        
        self.render('courselist.html')



"""
Handler for course registration
"""
class RegisterHandler(BaseHandler):

    def get(self, coursecode):
        user = users.get_current_user()
        if user:
            self.templateValue['email'] = user.email()
            self.templateValue['logoutUrl'] = users.create_logout_url('/')
    
        navbar = {'registration': True}
        self.templateValue['navbar'] = navbar
        # Check for existing registration -> redirect to course page
        student = Student.get_by_key_name(self.key(user.email()))
        if student is None:
            course = self.templateValue['coursesetup']
            if course is not None:
                if course.registration_questions:
                    regquestions = course.registration_questions
                else:
                    regquestions = '{ "q1" : "What is your name ?" }';
                self.templateValue['registration_questions'] = json.loads(regquestions)
                self.render('register.html')
            else:
                self.redirect('/' % coursecode)
        else:
            self.redirect('/%s/course' % coursecode)

    def post(self, coursecode):
        user = users.get_current_user()
        if user:
            email = user.email()
            self.templateValue['email'] = email
            self.templateValue['logoutUrl'] = users.create_logout_url('/')
        
        # Restrict the maximum course size to 250000 people
        # FIXME: you can change this number if you wish.
        students = self.course(Student.all(keys_only=True))
        if (students.count() > 249999):
            self.templateValue['course_status'] = 'full'
        
        # Create student record
        name = self.request.get('form01')
        student = Student(key_name=self.key(user.email()), 
                          coursecode=coursecode, 
                          name=name, 
                          email=user.email())
        student.put()
        
        # Render registration confirmation page
        navbar = {'registration': True,
                  'registered': True}
        self.templateValue['navbar'] = navbar
        self.render('confirmation.html')


"""
Handler for forum page
"""
class ForumHandler(BaseHandler):

    def get(self, coursecode):
        navbar = {'forum':True}
        self.templateValue['navbar'] = navbar
        user = users.get_current_user()
        if user:
            self.templateValue['email'] = user.email()
            self.templateValue['logoutUrl'] = users.create_logout_url('/')
        self.render('forum.html')


class DummySaveHandler(BaseHandler):
    def post(self, coursecode):
        pass


